<!DOCTYPE html>
<html>
<head>
<title>Piston Cylinder Diagram</title>
</head>
<body>
<canvas id="myCanvas" width="600" height="450" style="border:1px solid #d3d3d3;"></canvas>
<script>
// Get canvas and context
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// Clear canvas
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// --- Drawing parameters ---
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
ctx.lineWidth = 2;
ctx.font = '22px Arial';

// --- Dimensions ---
const pistonLeft = 120;
const pistonWidth = 25;
const pistonRight = pistonLeft + pistonWidth;
const cylinderLength = 320;
const cylinderRight = pistonRight + cylinderLength;
const cylinderTop = 100;
const cylinderBottom = 250;
const cylinderHeight = cylinderBottom - cylinderTop;
const yCenter = (cylinderTop + cylinderBottom) / 2;

// --- Helper function for drawing arrows ---
function drawArrow(ctx, fromx, fromy, tox, toy) {
    const headlen = 10;
    const dx = tox - fromx;
    const dy = toy - fromy;
    const angle = Math.atan2(dy, dx);
    ctx.beginPath();
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
    ctx.stroke();
}

// --- Draw components ---

// 1. Cylinder walls
ctx.beginPath();
ctx.moveTo(pistonLeft, cylinderTop);
ctx.lineTo(cylinderRight, cylinderTop);
ctx.moveTo(pistonLeft, cylinderBottom);
ctx.lineTo(cylinderRight, cylinderBottom);
ctx.moveTo(cylinderRight, cylinderTop);
ctx.lineTo(cylinderRight, cylinderBottom);
ctx.stroke();

// 2. Piston
ctx.beginPath();
ctx.rect(pistonLeft, cylinderTop, pistonWidth, cylinderHeight);
ctx.stroke();
// Hatching for the piston
ctx.save();
ctx.beginPath();
ctx.rect(pistonLeft, cylinderTop, pistonWidth, cylinderHeight);
ctx.clip(); // Clip to piston rectangle
ctx.lineWidth = 1.5;
for (let i = -cylinderHeight; i < pistonWidth + cylinderHeight; i += 10) {
    ctx.beginPath();
    ctx.moveTo(pistonLeft + i, cylinderTop);
    ctx.lineTo(pistonLeft + i - cylinderHeight, cylinderBottom);
    ctx.stroke();
}
ctx.restore();
ctx.lineWidth = 2; // Reset line width

// 3. Gas particles
const numParticles = 150;
for (let i = 0; i < numParticles; i++) {
    const x = pistonRight + 5 + Math.random() * (cylinderLength - 10);
    const y = cylinderTop + 5 + Math.random() * (cylinderHeight - 10);
    ctx.beginPath();
    ctx.arc(x, y, 1.5, 0, 2 * Math.PI);
    ctx.fill();
}

// 4. Force arrow and label
drawArrow(ctx, 40, yCenter, pistonLeft - 5, yCenter);
ctx.textAlign = 'left';
ctx.fillText('force', 45, yCenter + 30);

// 5. Piston label
ctx.textAlign = 'center';
ctx.fillText('piston', 250, 70);
ctx.beginPath();
ctx.moveTo(250, 80);
ctx.lineTo(pistonRight - 10, cylinderTop + 15);
ctx.stroke();

// 6. Length L indicator
const y_L = cylinderBottom + 40;
ctx.beginPath();
// Main line
ctx.moveTo(pistonRight, y_L);
ctx.lineTo(cylinderRight, y_L);
// Left arrowhead
ctx.moveTo(pistonRight + 12, y_L - 6);
ctx.lineTo(pistonRight, y_L);
ctx.lineTo(pistonRight + 12, y_L + 6);
// Right arrowhead
ctx.moveTo(cylinderRight - 12, y_L - 6);
ctx.lineTo(cylinderRight, y_L);
ctx.lineTo(cylinderRight - 12, y_L + 6);
ctx.stroke();
ctx.fillText('L', (pistonRight + cylinderRight) / 2, y_L + 25);

// 7. X-axis
const xAxisStart = cylinderRight;
const xAxisEnd = xAxisStart + 70;
drawArrow(ctx, xAxisStart, cylinderBottom, xAxisEnd, cylinderBottom);
ctx.textAlign = 'left';
ctx.fillText('x', xAxisEnd + 10, cylinderBottom + 8);

// 8. Figure caption
ctx.textAlign = 'center';
ctx.fillText('Fig. 1.46.', canvas.width / 2 - 20, cylinderBottom + 100);

</script>
</body>
</html>